package mutt.client;

import mutt.shared.Lang;
import mutt.shared.Lang.Labels;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ToggleButton;

import edu.ycp.cs.dh.acegwt.client.ace.AceEditor;
import edu.ycp.cs.dh.acegwt.client.ace.AceEditorCallback;
import edu.ycp.cs.dh.acegwt.client.ace.AceEditorMode;
import edu.ycp.cs.dh.acegwt.client.ace.AceEditorTheme;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class WebCalc implements EntryPoint {

	private static String NAMEFIELDCONTAINERSTRING = "nameFieldContainer";
	private static String SENDBUTTONCONTAINERSTRING = "sendButtonContainer";
	private static String ERRORLABELCONTAINERSTRING = "errorLabelContainer";
	private static String RESPONSECONTAINERSTRING = "responseContainer";
	private static String RESPONSESTYLE = "serverResponseLabelError";
	private static String QUERYBUTTONSTYLE = "sendButton";
	private static String COMMANDCONTAINERSTRING = "commandContainer";
	private static String INPUTFIELDWIDTH = "670px";
	private static String INPUTFIELDHEIGHT = "300px";
	private final CalcServiceAsync calcService = GWT.create(CalcService.class);

	/**
	 * Creates a handler <code>AceEditorCallback</code> class for the livetyping
	 * input
     *
     * @param labelLanguages
     *            - enum <code>Lang</code> with Estonian and English languages
     *            for the labels
     * @param inputField
     *            - field for user input
     * @param serverResponseLabel
     *            - response from the server: an error or calculation results
     * @param sendButton
     *            - button to send user input to server
     * @see Lang
	 */
	private void getPostQueryHandler(final Lang labelLanguages,
                                     final AceEditor inputField,
                                     final HTML serverResponseLabel,
                                     final ToggleButton sendButton) {

		if (!sendButton.isDown())
			return;

		// If livetyping is on, we send the input to the server.
		String textToServer = inputField.getText();

		serverResponseLabel.setText(labelLanguages
				._(Labels.serverResponseLabelText));

		calcService.doCalc(textToServer, new AsyncCallback<String>() {
			public void onFailure(Throwable caught) {
				// Show the RPC error message to the user
				serverResponseLabel.addStyleName(RESPONSESTYLE);
				serverResponseLabel.setHTML(labelLanguages
						._(Labels.SERVER_ERROR));
			}

			public void onSuccess(String result) {
				serverResponseLabel.removeStyleName(RESPONSESTYLE);
				serverResponseLabel.setHTML(result);
			}
		});
	}

	/**
	 * Initializes the user interface with a selected language.
	 * 
	 * @param labelLanguages
	 *            - enum <code>Lang</code> with Estonian and English languages
	 *            for the labels
	 * @see Lang
	 */
	public void getUI(Lang labelLanguages) {

		final ToggleButton sendButton = new ToggleButton(
				labelLanguages._(Labels.qButtonName));

		final AceEditor inputField = new AceEditor();
		final HTML serverResponseLabel = new HTML();
		final Label errorLabel = new Label();
		final HTML commandLabel = new HTML();
		final Label textToServerLabel = new Label();

		this.initHTMLConnection(labelLanguages, sendButton, inputField,
				errorLabel, commandLabel, serverResponseLabel
        );
	}

	/**
	 * Initializes HTML connection
	 *
     * @param labelLanguages
     *            - enum <code>Lang</code> with Estonian and English languages
     *            for the labels
     * @param sendButton
     *            - button to send user input to server
     * @param inputField
     *            - field for user input
     * @param errorLabel
     *            - label showing error if input is invalid
     * @param commandLabel
     *            - label asking user to enter query
     * @param serverResponseLabel
     * @see Lang
	 */
	public void initHTMLConnection(final Lang labelLanguages,
                                   final ToggleButton sendButton,
                                   final AceEditor inputField,
                                   final Label errorLabel,
                                   Label commandLabel,
                                   final HTML serverResponseLabel) {

		commandLabel.setText(labelLanguages._(Labels.commandlabel));
		inputField.setSize(INPUTFIELDWIDTH, INPUTFIELDHEIGHT);

		// Add the inputField and sendButton to the RootPanel
		// Use RootPanel.get() to get the entire body element
		RootPanel.get(COMMANDCONTAINERSTRING).add(commandLabel);
		RootPanel.get(NAMEFIELDCONTAINERSTRING).add(inputField);
		RootPanel.get(SENDBUTTONCONTAINERSTRING).add(sendButton);
		RootPanel.get(ERRORLABELCONTAINERSTRING).add(errorLabel);
		RootPanel.get(RESPONSECONTAINERSTRING).add(serverResponseLabel);

		// next line must be called before calling setTheme/setMode/etc.
		inputField.startEditor();
		inputField.setTheme(AceEditorTheme.ECLIPSE);
		inputField.setMode(AceEditorMode.RUBY);
		// sendButton.setDown(true);//turned off by default
		sendButton.addStyleName(QUERYBUTTONSTYLE);

		// Call the server if, button is pressed down or changes are made while
		// button is pressed down
		sendButton.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				getPostQueryHandler(labelLanguages, inputField,
                        serverResponseLabel, sendButton);
			}
		});
		inputField.addOnChangeHandler(new AceEditorCallback() {
			@Override
			public void invokeAceCallback(JavaScriptObject obj) {
				getPostQueryHandler(labelLanguages, inputField,
                        serverResponseLabel, sendButton);
			}
		});
	}

	/**
	 * This is the entry point method.
	 */
	public void onModuleLoad() {
		getUI(Lang.Estonian);
	}
}
